home *** CD-ROM | disk | FTP | other *** search
/ InfoMagic Internet Tools 1993 July / Internet Tools.iso / RockRidge / mail / elm / elm2.4 / src / elm.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-05-31  |  30.8 KB  |  1,090 lines

  1.  
  2. static char rcsid[] = "@(#)$Id: elm.c,v 5.14 1993/05/31 19:32:20 syd Exp $";
  3.  
  4. /*******************************************************************************
  5.  *  The Elm Mail System  -  $Revision: 5.14 $   $State: Exp $
  6.  *
  7.  * This file and all associated files and documentation:
  8.  *            Copyright (c) 1988-1992 USENET Community Trust
  9.  *            Copyright (c) 1986,1987 Dave Taylor
  10.  *******************************************************************************
  11.  * Bug reports, patches, comments, suggestions should be sent to:
  12.  *
  13.  *    Syd Weinstein, Elm Coordinator
  14.  *    elm@DSI.COM            dsinc!elm
  15.  *
  16.  *******************************************************************************
  17.  * $Log: elm.c,v $
  18.  * Revision 5.14  1993/05/31  19:32:20  syd
  19.  * With this patch build_address() should treat local mailing
  20.  * lists and other aliases known by the transport agent as valid
  21.  * addresses.
  22.  * I also conditionalized printing the "Expands to: " message
  23.  * in check_only mode to be done only when there is an expanded
  24.  * address to print. Build_address will inform anyway about an
  25.  * alias that does not exist.
  26.  * From: Jukka Ukkonen <ukkonen@csc.fi>
  27.  *
  28.  * Revision 5.13  1993/04/12  03:15:41  syd
  29.  * These patches makes 'T' (since it was free) do a Tag and Move command in the
  30.  * index and alias page, and in the builtin pager.
  31.  * In the alias help in src/alias.c, there is a tolower done on the character
  32.  * one wants help for.  This is clearly wrong.
  33.  * From: Jan Djarv <Jan.Djarv@sa.erisoft.se>
  34.  *
  35.  * Revision 5.12  1993/01/20  03:37:16  syd
  36.  * Nits and typos in the NLS messages and corresponding default messages.
  37.  * From: dwolfe@pffft.sps.mot.com (Dave Wolfe)
  38.  *
  39.  * Revision 5.11  1993/01/19  04:34:28  syd
  40.  * Just a small bugfix for the '#' (Debug Message) screen.  The columns of the
  41.  * various flags don't all line up properly:
  42.  * From: Gary Bartlett <garyb@abekrd.co.uk>
  43.  *
  44.  * Revision 5.10  1992/12/24  21:42:01  syd
  45.  * Fix messages and nls messages to match.  Plus use want_to
  46.  * where appropriate.
  47.  * From: Syd, via prompting from Jan Djarv <Jan.Djarv@sa.erisoft.se>
  48.  *
  49.  * Revision 5.9  1992/12/16  14:33:25  syd
  50.  * add back missing nl on check only output
  51.  * From: Syd
  52.  *
  53.  * Revision 5.8  1992/12/11  01:45:04  syd
  54.  * remove sys/types.h include, it is now included by defs.h
  55.  * and this routine includes defs.h or indirectly includes defs.h
  56.  * From: Syd
  57.  *
  58.  * Revision 5.7  1992/12/07  02:58:13  syd
  59.  * fix long -> time_t
  60.  * From: Syd
  61.  *
  62.  * Revision 5.6  1992/11/26  00:46:13  syd
  63.  * changes to first change screen back (Raw off) and then issue final
  64.  * error message.
  65.  * From: Syd
  66.  *
  67.  * Revision 5.5  1992/11/22  00:03:56  syd
  68.  * Fix segmentation violation on restricted alias page jump.
  69.  * From: "Robert L. Howard" <robert.howard@matd.gatech.edu>
  70.  *
  71.  * Revision 5.4  1992/11/07  19:37:21  syd
  72.  * Enhanced printing support.  Added "-I" to readmsg to
  73.  * suppress spurious diagnostic messages.
  74.  * From: chip@chinacat.unicom.com (Chip Rosenthal)
  75.  *
  76.  * Revision 5.3  1992/10/31  20:02:26  syd
  77.  * remove duplicate ScreenSize call
  78.  * From: Syd
  79.  *
  80.  * Revision 5.2  1992/10/25  01:47:45  syd
  81.  * fixed a bug were elm didn't call metamail on messages with a characterset,
  82.  * which could be displayed by elm itself, but message is encoded with QP
  83.  * or BASE64
  84.  * From: Klaus Steinberger <Klaus.Steinberger@Physik.Uni-Muenchen.DE>
  85.  *
  86.  * Revision 5.1  1992/10/03  22:58:40  syd
  87.  * Initial checkin as of 2.4 Release at PL0
  88.  *
  89.  *
  90.  ******************************************************************************/
  91.  
  92. /* Main program of the ELM mail system! 
  93. */
  94.  
  95. #include "elm.h"
  96. #include "s_elm.h"
  97.  
  98. #ifdef I_TIME
  99. #  include <time.h>
  100. #endif
  101. #ifdef I_SYSTIME
  102. #  include <sys/time.h>
  103. #endif
  104. #ifdef BSD
  105. #  include <sys/timeb.h>
  106.  
  107. #undef        toupper
  108. #undef        tolower
  109.  
  110. #endif
  111.  
  112. long bytes();
  113. char *format_long(), *parse_arguments(), *error_description();
  114.  
  115. main(argc, argv)
  116. int argc;
  117. char *argv[];
  118. {
  119.     int  ch;
  120.     char address[SLEN], to_whom[SLEN], *req_mfile;
  121.     int  i,j;              /** Random counting variables (etc)          **/
  122.     int  pageon,         /** for when we receive new mail...          **/
  123.          last_in_folder;    /** for when we receive new mail too...      **/
  124.     long num;        /** another variable for fun..               **/
  125.     extern int errno;
  126.  
  127. #ifdef I_LOCALE
  128.     setlocale(LC_ALL, "");
  129. #endif
  130.  
  131.     elm_msg_cat = catopen("elm2.4", 0);
  132.  
  133.     req_mfile = parse_arguments(argc, argv, to_whom);
  134.  
  135.     initialize(req_mfile);
  136.  
  137.     if (mail_only) {
  138.        dprint(3, (debugfile, "Mail-only: mailing to\n-> \"%s\"\n", 
  139.            format_long(to_whom, 3)));
  140.        if(!batch_only) {
  141.          sprintf(address, catgets(elm_msg_cat, ElmSet, ElmSendOnlyMode,
  142.            "Send only mode [ELM %s]"), version_buff);
  143.          Centerline(1, address);
  144.        }
  145.        (void) send_msg(to_whom, "", batch_subject, TRUE,
  146.          (batch_only ? NO : allow_forms), FALSE); 
  147.        leave(0);
  148.     } else if (check_only) {
  149.        do_check_only(to_whom);
  150.        leave(0);
  151.     }
  152.  
  153.     showscreen();
  154.  
  155.     while (1) {
  156. #ifdef SIGWINCH
  157.       if (resize_screen) {
  158.         int    newLINES, newCOLUMNS;
  159.  
  160.         ScreenSize(&newLINES, &newCOLUMNS);
  161.         resize_screen = 0;
  162.         if (newLINES != LINES || newCOLUMNS != COLUMNS) {
  163.           LINES = newLINES, COLUMNS = newCOLUMNS;
  164. #define max(a,b)           ((a) < (b) ? (b) : (a))
  165.           if (mini_menu)
  166.         headers_per_page = max (LINES - 13, 1);
  167.           else
  168.         headers_per_page = max (LINES -     8, 1);      /* 5 more headers! */
  169. #undef max
  170.           redraw++;
  171.         }
  172.       }
  173.       else redraw = 0;
  174. #else
  175.           redraw = 0;
  176. #endif
  177.       nufoot = 0;
  178.       nucurr = 0;
  179.       if ((num = bytes(cur_folder)) != mailfile_size) {
  180.         dprint(2, (debugfile, "Just received %d bytes more mail (elm)\n", 
  181.             num - mailfile_size));
  182.         error(catgets(elm_msg_cat, ElmSet, ElmNewMailHangOn,
  183.           "New mail has arrived! Hang on..."));
  184.         fflush(stdin);    /* just to be sure... */
  185.         last_in_folder = message_count;
  186.         pageon = header_page;
  187.  
  188.         if ((errno = can_access(cur_folder, READ_ACCESS)) != 0) {
  189.           dprint(1, (debugfile,
  190.             "Error: given file %s as folder - unreadable (%s)!\n", 
  191.             cur_folder, error_description(errno)));
  192.           Raw(OFF);
  193.           fprintf(stderr, catgets(elm_msg_cat, ElmSet, ElmCantOpenFolderRead,
  194.         "Can't open folder '%s' for reading!\n"), cur_folder);
  195.           leave(0);
  196.           }
  197.  
  198.         newmbox(cur_folder, TRUE);    /* last won't be touched! */
  199.         clear_error();
  200.         header_page = pageon;
  201.  
  202.         if (on_page(current))   /* do we REALLY have to rewrite? */
  203.           showscreen();
  204.         else {
  205.           update_title();
  206.           ClearLine(LINES-1);         /* remove reading message... */
  207.           if ((message_count - last_in_folder) == 1)
  208.             error(catgets(elm_msg_cat, ElmSet, ElmNewMessageRecv,
  209.                "1 new message received."));
  210.           else
  211.             error1(catgets(elm_msg_cat, ElmSet, ElmNewMessageRecvPlural,
  212.                "%d new messages received."), 
  213.                message_count - last_in_folder);
  214.         }
  215.         /* mailfile_size = num; */
  216.         if (cursor_control)
  217.           transmit_functions(ON);    /* insurance */
  218.       }
  219.  
  220.       prompt(Prompt);
  221.  
  222.       CleartoEOLN();
  223.       ch = GetPrompt();
  224. #ifdef SIGWINCH
  225.       if (resize_screen) {
  226.         int    newLINES, newCOLUMNS;
  227.  
  228.         ScreenSize(&newLINES, &newCOLUMNS);
  229.         resize_screen = 0;
  230.         if (newLINES != LINES || newCOLUMNS != COLUMNS) {
  231.           LINES = newLINES, COLUMNS = newCOLUMNS;
  232. #define max(a,b)           ((a) < (b) ? (b) : (a))
  233.           if (mini_menu)
  234.         headers_per_page = max (LINES - 13, 1);
  235.           else
  236.         headers_per_page = max (LINES -     8, 1);      /* 5 more headers! */
  237. #undef max
  238.           redraw++;
  239.         }
  240.       }
  241. #endif
  242.       CleartoEOS();
  243. #ifdef DEBUG
  244.       if (! movement_command(ch))
  245.         dprint(4, (debugfile, "\nCommand: %c [%d]\n\n", ch, ch));
  246. #endif
  247.  
  248.       set_error("");    /* clear error buffer */
  249.  
  250.       MoveCursor(LINES-3,strlen(Prompt));
  251.  
  252.       switch (ch) {
  253.  
  254.         case '?'     :  if (help(FALSE))
  255.                    redraw++;
  256.                else
  257.                  nufoot++;
  258.                break;
  259.  
  260.         case '$'    :  PutLine0(LINES-3, strlen(Prompt),
  261.                  catgets(elm_msg_cat, ElmSet, ElmResyncFolder,
  262.                      "Resynchronize folder"));
  263.                redraw += resync();
  264.                nucurr = get_page(current);
  265.                break;
  266.  
  267.         case '|'    :  Writechar('|'); 
  268.                if (message_count < 1) {
  269.                  error(catgets(elm_msg_cat, ElmSet, ElmNoMailToPipe,
  270.                    "No mail to pipe!"));
  271.                  fflush(stdin);
  272.                } else {
  273.                      softkeys_off();
  274.                              redraw += do_pipe();        
  275.                  softkeys_on();
  276.                }
  277.                break;
  278.  
  279. #ifdef ALLOW_SUBSHELL
  280.         case '!'    :  Writechar('!'); 
  281.                            redraw += subshell();        
  282.                break;
  283. #endif
  284.  
  285.         case '%'    :  if (current > 0) {
  286.                  get_return(address, current-1);
  287.                  clear_error();
  288.                  PutLine1(LINES,(COLUMNS-strlen(address))/2,
  289.                       "%.78s", address);    
  290.                } else {
  291.                  error(catgets(elm_msg_cat, ElmSet, ElmNoMailReturnAddress,
  292.                    "No mail to get return address of!")); 
  293.                  fflush(stdin);
  294.                }
  295.                break;
  296.  
  297.         case '<'    :  /* scan current message for calendar information */
  298. #ifdef ENABLE_CALENDAR
  299.                if  (message_count < 1) {
  300.                  error(catgets(elm_msg_cat, ElmSet, ElmNoMailToScan,
  301.                    "No mail to scan!"));
  302.                  fflush(stdin);
  303.                }
  304.                else {
  305.                    PutLine0(LINES-3, strlen(Prompt),     
  306.                        catgets(elm_msg_cat, ElmSet, ElmScanForCalendar,
  307.                    "Scan message for calendar entries..."));
  308.                    scan_calendar();
  309.                }
  310. #else
  311.                 error(catgets(elm_msg_cat, ElmSet, ElmSorryNoCalendar,
  312.                  "Sorry. Calendar function disabled."));
  313.                fflush(stdin);
  314. #endif
  315.                break;
  316.  
  317.         case 'a'    :  alias();
  318.                redraw++;
  319.                define_softkeys(MAIN);     break;
  320.             
  321.         case 'b'    :  PutLine0(LINES-3, strlen(Prompt), 
  322.                  catgets(elm_msg_cat, ElmSet, ElmBounceMessage,
  323.                  "Bounce message"));
  324.                fflush(stdout);
  325.                if (message_count < 1) {
  326.                    error(catgets(elm_msg_cat, ElmSet, ElmNoMailToBounce,
  327.                    "No mail to bounce!"));
  328.                  fflush(stdin);
  329.                }
  330.                else 
  331.                  nufoot = remail();
  332.                break;
  333.  
  334.         case 'c'    :  PutLine0(LINES-3, strlen(Prompt), 
  335.                  catgets(elm_msg_cat, ElmSet, ElmChangeFolder,
  336.                  "Change folder"));
  337.                define_softkeys(CHANGE);
  338.                redraw += change_file();
  339.                define_softkeys(MAIN);
  340.                break;
  341.  
  342. #ifdef ALLOW_MAILBOX_EDITING
  343.         case 'e'    :  PutLine0(LINES-3,strlen(Prompt),
  344.                  catgets(elm_msg_cat, ElmSet, ElmEditFolder,
  345.                  "Edit folder"));
  346.                if (current > 0) {
  347.                  edit_mailbox();
  348.                      if (cursor_control)
  349.                    transmit_functions(ON);    /* insurance */
  350.                   }
  351.                else {
  352.                  error(catgets(elm_msg_cat, ElmSet, ElmFolderIsEmpty,
  353.                    "Folder is empty!"));
  354.                  fflush(stdin);
  355.                }
  356.                break;
  357. #else
  358.         case 'e'    : error(catgets(elm_msg_cat, ElmSet, ElmNoFolderEdit,
  359.             "Folder editing isn't configured in this version of ELM."));
  360.               fflush(stdin);
  361.               break;
  362. #endif
  363.         
  364.         case 'f'    :  PutLine0(LINES-3, strlen(Prompt),
  365.                  catgets(elm_msg_cat, ElmSet, ElmForward,
  366.                  "Forward"));
  367.                define_softkeys(YESNO);
  368.                if (current > 0) {
  369.                  if(forward()) redraw++;
  370.                  else nufoot++;
  371.                } else {
  372.                  error(catgets(elm_msg_cat, ElmSet, ElmNoMailToForward,
  373.                    "No mail to forward!"));
  374.                  fflush(stdin);
  375.                }
  376.                define_softkeys(MAIN);
  377.                break;
  378.  
  379.         case 'g'    :  PutLine0(LINES-3,strlen(Prompt),
  380.                  catgets(elm_msg_cat, ElmSet, ElmGroupReply,
  381.                  "Group reply"));
  382.                fflush(stdout);
  383.                if (current > 0) {
  384.                  if (headers[current-1]->status & FORM_LETTER) {
  385.                    error(catgets(elm_msg_cat, ElmSet, ElmCantGroupReplyForm,
  386.                  "Can't group reply to a Form!!"));
  387.                    fflush(stdin);
  388.                  }
  389.                  else {
  390.                    define_softkeys(YESNO);
  391.                    redraw += reply_to_everyone();    
  392.                    define_softkeys(MAIN);
  393.                  }
  394.                }
  395.                else {
  396.                  error(catgets(elm_msg_cat, ElmSet, ElmNoMailToReply,
  397.                    "No mail to reply to!")); 
  398.                  fflush(stdin);
  399.                }
  400.                break;
  401.  
  402.         case 'h'    :  if (filter)
  403.                  PutLine0(LINES-3, strlen(Prompt), 
  404.                    catgets(elm_msg_cat, ElmSet, ElmMessageWithHeaders,
  405.                    "Message with headers..."));
  406.                else
  407.                  PutLine0(LINES-3, strlen(Prompt),
  408.                    catgets(elm_msg_cat, ElmSet, ElmDisplayMessage,
  409.                    "Display message"));
  410.                if(current > 0) {
  411.                  fflush(stdout);
  412.                  j = filter;
  413.                  filter = FALSE;
  414.                  i = show_msg(current);
  415.                  while (i)
  416.                 i = process_showmsg_cmd(i);
  417.                  filter = j;
  418.                  redraw++;
  419.                  (void)get_page(current);
  420.                } else
  421.                  error(catgets(elm_msg_cat, ElmSet, ElmNoMailToRead,
  422.                    "No mail to read!"));
  423.                break;
  424.  
  425.         case 'm'    :  PutLine0(LINES-3, strlen(Prompt),
  426.                  catgets(elm_msg_cat, ElmSet, ElmMail,
  427.                  "Mail"));
  428.                 redraw += send_msg("", "", "", TRUE,allow_forms,FALSE); 
  429.                break;
  430.  
  431.         case ' '    : 
  432.         case ctrl('J'):
  433.         case ctrl('M'): PutLine0(LINES-3, strlen(Prompt), 
  434.                   catgets(elm_msg_cat, ElmSet, ElmDisplayMessage,
  435.                       "Display message"));    
  436.                fflush(stdout);
  437.                if(current > 0 ) {
  438.                  define_softkeys(READ);
  439.  
  440.                  i = show_msg(current);
  441.                  while (i)
  442.                 i = process_showmsg_cmd(i);
  443.                  redraw++;
  444.                  (void)get_page(current);
  445.                } else
  446.                  error(catgets(elm_msg_cat, ElmSet, ElmNoMailToRead,
  447.                    "No mail to read!"));
  448.                break;
  449.  
  450.         case 'n'    :  PutLine0(LINES-3,strlen(Prompt),
  451.                  catgets(elm_msg_cat, ElmSet, ElmNextMessage,
  452.                  "Next Message"));
  453.                fflush(stdout);
  454.                define_softkeys(READ);
  455.  
  456.                if(current > 0 ) {
  457.                  define_softkeys(READ);
  458.  
  459.                  i = show_msg(current);
  460.                  while (i)
  461.                    i = process_showmsg_cmd(i);
  462.                  redraw++;
  463.                  if (++current > message_count)
  464.                    current = message_count;
  465.                  (void)get_page(current);
  466.                } else
  467.                  error(catgets(elm_msg_cat, ElmSet, ElmNoMailToRead,
  468.                    "No mail to read!"));
  469.                break;
  470.  
  471.         case 'o'    :  PutLine0(LINES-3, strlen(Prompt),
  472.                  catgets(elm_msg_cat, ElmSet, ElmOptions,
  473.                  "Options"));
  474.                if((i=options()) > 0)
  475.                  get_page(current);
  476.                else if(i < 0)
  477.                  leave(0);
  478.                redraw++;    /* always fix da screen... */
  479.                break;
  480.  
  481.         case 'p'    :  PutLine0(LINES-3, strlen(Prompt),
  482.                  catgets(elm_msg_cat, ElmSet, ElmPrintMail,
  483.                  "Print mail"));
  484.                fflush(stdout);
  485.                if (message_count < 1) {
  486.                  error(catgets(elm_msg_cat, ElmSet, ElmNoMailToPrint,
  487.                    "No mail to print!"));
  488.                  fflush(stdin);
  489.                } else if (print_msg(TRUE) != 0)
  490.                  redraw++;
  491.                break;
  492.  
  493.         case 'q'    :  PutLine0(LINES-3, strlen(Prompt),
  494.                  catgets(elm_msg_cat, ElmSet, ElmQuit,
  495.                  "Quit"));
  496.  
  497.                if (mailfile_size != bytes(cur_folder)) {
  498.                  error(catgets(elm_msg_cat, ElmSet, ElmNewMailQuitCancelled,
  499.                 "New Mail!  Quit canceled..."));
  500.                  fflush(stdin);
  501.                    if (folder_type == SPOOL) unlock();
  502.                }
  503.                else
  504.                  quit(TRUE);        
  505.  
  506.                break;
  507.  
  508.         case 'Q'    :  PutLine0(LINES-3, strlen(Prompt),
  509.                  catgets(elm_msg_cat, ElmSet, ElmQuickQuit,
  510.                  "Quick quit"));
  511.  
  512.                if (mailfile_size != bytes(cur_folder)) {
  513.                  error(catgets(elm_msg_cat, ElmSet, ElmNewMailQuickQuitCancelled,
  514.                    "New Mail!  Quick Quit canceled..."));
  515.                    if (folder_type == SPOOL) unlock();
  516.                }
  517.                else
  518.                  quit(FALSE);        
  519.  
  520.                break;
  521.  
  522.         case 'r'    :  PutLine0(LINES-3, strlen(Prompt), 
  523.                  catgets(elm_msg_cat, ElmSet, ElmReplyToMessage,
  524.                  "Reply to message"));
  525.                if (current > 0) 
  526.                  redraw += reply();    
  527.                else {
  528.                  error(catgets(elm_msg_cat, ElmSet, ElmNoMailToReplyTo,
  529.                    "No mail to reply to!")); 
  530.                  fflush(stdin);
  531.                }
  532.                softkeys_on();
  533.                break;
  534.  
  535.         case '>'    : /** backwards compatibility **/
  536.  
  537.         case 'C'    :
  538.         case 's'    :  if  (message_count < 1) {
  539.                  if (ch != 'C')
  540.                    error(catgets(elm_msg_cat, ElmSet, ElmNoMailToSave,
  541.                  "No mail to save!"));
  542.                  else
  543.                    error(catgets(elm_msg_cat, ElmSet, ElmNoMailToCopy,
  544.                  "No mail to copy!"));
  545.                  fflush(stdin);
  546.                }
  547.                else {
  548.                  if (ch != 'C')
  549.                    PutLine0(LINES-3, strlen(Prompt),
  550.                       catgets(elm_msg_cat, ElmSet, ElmSaveToFolder,
  551.                       "Save to folder"));
  552.                  else
  553.                    PutLine0(LINES-3, strlen(Prompt),
  554.                       catgets(elm_msg_cat, ElmSet, ElmCopyToFolder,
  555.                       "Copy to folder"));
  556.                  PutLine0(LINES-3,COLUMNS-40,
  557.                     catgets(elm_msg_cat, ElmSet, ElmUseForHelp,
  558.                 "(Use '?' for help)"));
  559.                  if (save(&redraw, FALSE, (ch != 'C'))
  560.                  && resolve_mode && ch != 'C') {
  561.                    if((i=next_message(current-1, TRUE)) != -1) {
  562.                  current = i+1;
  563.                  nucurr = get_page(current);
  564.                    }
  565.                  }
  566.                }
  567.                ClearLine(LINES-2);        
  568.                break;
  569.  
  570.         case 'X'    :  PutLine0(LINES-3, strlen(Prompt),
  571.                  catgets(elm_msg_cat, ElmSet, ElmQuickExit,
  572.                  "Quick Exit"));
  573.                            fflush(stdout);
  574.                leave(0);
  575.                break;
  576.  
  577.         case ctrl('Q') :
  578.         case 'x'    :  PutLine0(LINES-3, strlen(Prompt),
  579.                  catgets(elm_msg_cat, ElmSet, ElmExit,
  580.                  "Exit"));  
  581.                            fflush(stdout);
  582.                exit_prog();
  583.                break;
  584.  
  585.             case EOF :  leave(0);  /* Read failed, control tty died? */
  586.                         break;
  587.         
  588.         case '@'    : debug_screen();  redraw++;    break;
  589.     
  590.         case '#'    : if (message_count) {
  591.                 debug_message(); 
  592.                 redraw++;    
  593.               } 
  594.               else {
  595.                 error(catgets(elm_msg_cat, ElmSet, ElmNoMailToCheck,
  596.                   "No mail to check."));
  597.                 fflush(stdin);
  598.               }
  599.               break;
  600.  
  601.         /* None of the menu specific commands were chosen, therefore
  602.          * it must be a "motion" command (or an error).               */
  603.         default    : motion(ch);
  604.  
  605.       }
  606.  
  607.       if (redraw)
  608.         showscreen();
  609.  
  610.           check_range();
  611.         
  612.       if (nucurr == NEW_PAGE) 
  613.         show_headers();
  614.       else if (nucurr == SAME_PAGE)
  615.         show_current();
  616.       else if (nufoot) {
  617.         if (mini_menu) {
  618.           MoveCursor(LINES-7, 0);  
  619.               CleartoEOS();
  620.           show_menu();
  621.         }
  622.         else {
  623.           MoveCursor(LINES-4, 0);
  624.           CleartoEOS();
  625.         }
  626.         show_last_error();    /* for those operations that have to
  627.                  * clear the footer except for a message.
  628.                  */
  629.       }
  630.  
  631.     } /* the BIG while loop! */
  632. }
  633.  
  634. debug_screen()
  635. {
  636.     /**** spit out all the current variable settings and the table
  637.           entries for the current 'n' items displayed. ****/
  638.  
  639.     register int i, j;
  640.     char     buffer[SLEN];
  641.  
  642.     ClearScreen();
  643.  
  644.     PutLine2(0,0,"Current message number = %d\t\t%d message(s) total\n",
  645.         current, message_count);
  646.     PutLine2(2,0,"Header_page = %d           \t\t%d possible page(s)\n",
  647.         header_page, (int) (message_count / headers_per_page) + 1);
  648.  
  649.     PutLine1(4,0,"\nCurrent mail file is %s.\n\r\n", cur_folder);
  650.  
  651.     i = header_page*headers_per_page;    /* starting header */
  652.  
  653.     if ((j = i + (headers_per_page-1)) >= message_count) 
  654.       j = message_count-1;
  655.  
  656.     Write_to_screen(
  657. "Num      From                    Subject                Lines   Offset  Content\n\r\n\r",0);
  658.  
  659.     while (i <= j) {
  660.        sprintf(buffer, 
  661.        "%3d %-16.16s %-35.35s %4d %8d %8d\n\r",
  662.             i+1,
  663.             headers[i]->from, 
  664.             headers[i]->subject,
  665.             headers[i]->lines,
  666.             headers[i]->offset,
  667.             headers[i]->content_length);
  668.         Write_to_screen(buffer, 0);
  669.       i++;
  670.     }
  671.     
  672.     PutLine0(LINES,0,"Press any key to return.");
  673.     (void) ReadCh();
  674. }
  675.  
  676.  
  677. debug_message()
  678. {
  679.     /**** Spit out the current message record.  Include EVERYTHING
  680.           in the record structure. **/
  681.     
  682.     char buffer[SLEN];
  683.     time_t header_time;
  684.     register struct header_rec *current_header = headers[current-1];
  685.  
  686.     ClearScreen();
  687.  
  688.     Write_to_screen("\t\t\t----- Message %d -----\n\r\n\r\n\r\n\r", 1,
  689.         current);
  690.  
  691.     Write_to_screen(     "Lines : %-5d\t\t\tStatus: A  C  D  E  F  M  D  N  N  O  P  T  U  V\n\r", 1,
  692.         current_header->lines);
  693.     Write_to_screen("Content-Length: %-12d\t        c  o  e  x  o  i  e  p  e  l  r  a  r  i\n\r", 1,
  694.         current_header->content_length);
  695.     Write_to_screen(     "            \t\t\t        t  n  l  p  r  m  c  l  w  d  i  g  g  s\n\r", 0);
  696.     Write_to_screen(     "            \t\t\t        n  f  d  d  m  e  o  a        v  d  n  i\n\r", 0);
  697.  
  698.     sprintf(buffer, 
  699.         "\n\rOffset: %ld\t\t\t        %d  %d  %d  %d  %d  %d  %d  %d",
  700.         current_header->offset,
  701.         (current_header->status & ACTION) != 0,
  702.         (current_header->status & CONFIDENTIAL) != 0,
  703.         (current_header->status & DELETED) != 0,
  704.         (current_header->status & EXPIRED) != 0,
  705.         (current_header->status & FORM_LETTER) != 0,
  706.         (current_header->status & MIME_MESSAGE) != 0,
  707.         (current_header->status & MIME_NEEDDECOD) != 0,
  708.         (current_header->status & MIME_NOTPLAIN) != 0);
  709.     sprintf(buffer + strlen(buffer),
  710.         "  %d  %d  %d  %d  %d  %d\n",
  711.         (current_header->status & NEW) != 0,
  712.         (current_header->status & UNREAD) != 0,
  713.         (current_header->status & PRIVATE) != 0,
  714.         (current_header->status & TAGGED) != 0,
  715.         (current_header->status & URGENT) != 0,
  716.         (current_header->status & VISIBLE) != 0);
  717.  
  718.     Write_to_screen(buffer, 0);
  719.  
  720.     sprintf(buffer, "\n\rReceived on: %s\r",
  721.         asctime(localtime(¤t_header->received_time)));
  722.     Write_to_screen(buffer, 0);
  723.  
  724.     header_time = current_header->time_sent + current_header->tz_offset;
  725.     sprintf(buffer, "Message sent on: %s\rFrom timezone: %s (%d)\n\r",
  726.         asctime(gmtime(&header_time)),
  727.         current_header->time_zone,
  728.         current_header->tz_offset);
  729.     Write_to_screen(buffer, 0);
  730.     
  731.     Write_to_screen("From: %s\n\rSubject: %s", 2,
  732.         current_header->from,
  733.         current_header->subject);
  734.  
  735.     Write_to_screen("\n\rPrimary Recipient: %s\nInternal Index Reference Number = %d\n\r", 2,
  736.         current_header->to,
  737.         current_header->index_number);
  738.  
  739.     Write_to_screen("Message-ID: %s\n\r", 1,
  740.         strlen(current_header->messageid) > 0 ? 
  741.         current_header->messageid : "<none>");
  742.  
  743.     Write_to_screen("Status: %s\n\r", 1, current_header->mailx_status);
  744.     
  745.     PutLine0(LINES,0,"Please Press any key to return.");
  746.     (void) ReadCh();
  747. }
  748.  
  749. do_check_only(to_whom)
  750. char *to_whom;
  751. {
  752.     char buffer[VERY_LONG_STRING], *msg;
  753.  
  754.     dprint(3, (debugfile, "Check-only: checking \n-> \"%s\"\n", 
  755.         format_long(to_whom, 3)));
  756.  
  757.     if (build_address(strip_commas(to_whom), buffer)) {
  758.  
  759.         msg = catgets(elm_msg_cat, ElmSet, ElmExpandsTo,
  760.               "Expands to: ");
  761.         printf(msg);
  762.  
  763.         printf("%s\n", format_long(buffer, strlen(msg)));
  764.     }
  765. }
  766.  
  767. check_range()
  768. {
  769.     int i;
  770.  
  771.     i = compute_visible(current);
  772.  
  773.     if ((current < 1) || (selected && i < 1)) {
  774.         if (message_count > 0) {
  775.           /* We are out of range! Get to first message! */
  776.           if (selected)
  777.         current = compute_visible(1);
  778.           else
  779.         current = 1;
  780.         }
  781.         else
  782.           current = 0;
  783.     }
  784.     else if ((current > message_count)
  785.            || (selected && i > selected)) {
  786.         if (message_count > 0) {
  787.           /* We are out of range! Get to last (visible) message! */
  788.           if (selected)
  789.         current = visible_to_index(selected)+1;
  790.           else
  791.         current = message_count;
  792.         }
  793.         else
  794.           current = 0;
  795.     }
  796.  
  797. }
  798.  
  799. static char *no_mail = NULL;
  800. static char *no_aliases = NULL;
  801.  
  802. motion(ch)
  803. char ch;
  804. {
  805.     /* Consolidated the standard menu navigation and delete/tag
  806.      * commands to a function.                                   */
  807.  
  808.     int  key_offset;        /** Position offset within keyboard string   **/
  809.     int  i;
  810.  
  811.     if (no_mail == NULL) {
  812.         no_mail = catgets(elm_msg_cat, ElmSet, ElmNoMailInFolder,
  813.           "No mail in folder!");
  814.         no_aliases = catgets(elm_msg_cat, ElmSet, ElmNoAliases,
  815.           "No aliases!");
  816.     }
  817.  
  818.     switch (ch) {
  819.  
  820.         case '/'    :  /* scan mbox or aliases for string */
  821.                if  (message_count < 1) {
  822.                  error1(catgets(elm_msg_cat, ElmSet,
  823.                 ElmNoItemToScan, "No %s to scan!"), items);
  824.                  fflush(stdin);
  825.                }
  826.                else if (pattern_match())
  827.                  nucurr = get_page(current);
  828.                else {
  829.                  error(catgets(elm_msg_cat, ElmSet, ElmPatternNotFound,
  830.                    "pattern not found!"));
  831.                  fflush(stdin);
  832.                }
  833.                break;
  834.  
  835. next_page:
  836.         case '+'    :  /* move to next page if we're not on the last */
  837.                if((selected &&
  838.                  ((header_page+1)*headers_per_page < selected))
  839.                ||(!selected &&
  840.                  ((header_page+1)*headers_per_page<message_count))){
  841.  
  842.                  header_page++;
  843.                  nucurr = NEW_PAGE;
  844.  
  845.                  if(move_when_paged) {
  846.                    /* move to first message of new page */
  847.                    if(selected)
  848.                  current = visible_to_index(
  849.                    header_page * headers_per_page + 1) + 1;
  850.                    else
  851.                  current = header_page * headers_per_page + 1;
  852.                  }
  853.                } else
  854.                  error(catgets(elm_msg_cat, ElmSet, ElmAlreadyOnLastPage,
  855.                    "Already on last page."));
  856.                break;
  857.  
  858. prev_page:
  859.         case '-'    :  /* move to prev page if we're not on the first */
  860.                if(header_page > 0) {
  861.                  header_page--;
  862.                  nucurr = NEW_PAGE;
  863.  
  864.                  if(move_when_paged) {
  865.                    /* move to first message of new page */
  866.                    if(selected)
  867.                  current = visible_to_index(
  868.                    header_page * headers_per_page + 1) + 1;
  869.                    else
  870.                  current = header_page * headers_per_page + 1;
  871.                  }
  872.                } else
  873.                  error(catgets(elm_msg_cat, ElmSet, ElmAlreadyOnFirstPage,
  874.                    "Already on first page."));
  875.                break;
  876.  
  877. first_msg:
  878.         case '='    :  if (selected)
  879.                  current = visible_to_index(1)+1;
  880.                else
  881.                  current = 1;
  882.                nucurr = get_page(current);
  883.                break;
  884.  
  885. last_msg:
  886.         case '*'    :  if (selected) 
  887.                  current = (visible_to_index(selected)+1);
  888.                else
  889.                  current = message_count;    
  890.                nucurr = get_page(current);
  891.                break;
  892.  
  893.         case ctrl('D') :
  894.         case '^'    :
  895.         case 'd'    :  if (message_count < 1) {
  896.                  error1(catgets(elm_msg_cat, ElmSet, ElmNoItemToDelete,
  897.                    "No %s to delete!"), item);
  898.                  fflush(stdin);
  899.                }
  900.                else {
  901.                  if(ch == ctrl('D')) {
  902.  
  903.                    /* if current item did not become deleted,
  904.                 * don't to move to the next undeleted item */
  905.                    if(!meta_match(DELETED)) break;
  906.  
  907.                  } else 
  908.                     delete_msg((ch == 'd'), TRUE);
  909.  
  910.                  if (resolve_mode)     /* move after mail resolved */
  911.                    if((i=next_message(current-1, TRUE)) != -1) {
  912.                  current = i+1;
  913.                  nucurr = get_page(current);
  914.                    }
  915.                }
  916.                break;
  917.  
  918.         case 'J'    :  if(current > 0) {
  919.                  if((i=next_message(current-1, FALSE)) != -1) {
  920.                    current = i+1;
  921.                    nucurr = get_page(current);
  922.                  } else
  923.                    error1(catgets(elm_msg_cat, ElmSet, ElmNoMoreItemBelow,
  924.                  "No more %s below."), items);
  925.                } else error(ifmain(no_mail, no_aliases));
  926.                break;
  927.  
  928. next_undel_msg:
  929.         case 'j'    :  if(current > 0) {
  930.                  if((i=next_message(current-1, TRUE)) != -1) {
  931.                    current = i+1;
  932.                    nucurr = get_page(current);
  933.                  } else
  934.                    error1(catgets(elm_msg_cat, ElmSet, ElmNoItemUndeletedBelow,
  935.                  "No more undeleted %s below."), items);
  936.                } else error(ifmain(no_mail, no_aliases));
  937.                break;
  938.  
  939.         case 'K'    :  if(current > 0) {
  940.                  if((i=prev_message(current-1, FALSE)) != -1) {
  941.                    current = i+1;
  942.                    nucurr = get_page(current);
  943.                  } else
  944.                    error1(catgets(elm_msg_cat, ElmSet, ElmNoMoreItemAbove,
  945.                  "No more %s above."), items);
  946.                } else error(ifmain(no_mail, no_aliases));
  947.                break;
  948.  
  949. prev_undel_msg:
  950.         case 'k'    :  if(current > 0) {
  951.                  if((i=prev_message(current-1, TRUE)) != -1) {
  952.                    current = i+1;
  953.                    nucurr = get_page(current);
  954.                  } else
  955.                    error1(catgets(elm_msg_cat, ElmSet, ElmNoMoreUndeletedAbove,
  956.                  "No more undeleted %s above."), items);
  957.                } else error(ifmain(no_mail, no_aliases));
  958.                break;
  959.  
  960.         case 'l'    :  PutLine1(LINES-3, strlen(Prompt),
  961.                    catgets(elm_msg_cat, ElmSet, ElmLimitDisplayBy,
  962.                    "Limit displayed %s by..."), items);
  963.                clear_error();
  964.                if (limit() != 0) {
  965.                  get_page(current);
  966.                  redraw++;
  967.                } else {
  968.                  nufoot++;
  969.                }
  970.                break;
  971.  
  972.             case ctrl('T') :
  973.         case 'T'       :
  974.         case 't'       :  if (message_count < 1) {
  975.                 error1(catgets(elm_msg_cat, ElmSet, ElmNoItemToTag,
  976.                   "No %s to tag!"), items);
  977.                 fflush(stdin);
  978.                   }
  979.                   else if (ch == 't')
  980.                 tag_message(TRUE); 
  981.                   else if (ch == 'T') {
  982.                 tag_message(TRUE); 
  983.                 goto next_undel_msg;
  984.                   }
  985.                   else
  986.                 meta_match(TAGGED);
  987.                   break;
  988.  
  989.         case 'u'    :  if (message_count < 1) {
  990.                  error1(catgets(elm_msg_cat, ElmSet, ElmNoItemToMarkUndeleted,
  991.                    "No %s to mark as undeleted!"), items);
  992.                  fflush(stdin);
  993.                }
  994.                else {
  995.                  undelete_msg(TRUE);
  996.                  if (resolve_mode)     /* move after mail resolved */
  997.                    if((i=next_message(current-1, FALSE)) != -1) {
  998.                  current = i+1;
  999.                  nucurr = get_page(current);
  1000.                    }
  1001. /*************************************************************************
  1002.  **  What we've done here is to special case the "U)ndelete" command to
  1003.  **  ignore whether the next message is marked for deletion or not.  The
  1004.  **  reason is obvious upon usage - it's a real pain to undelete a series
  1005.  **  of messages without this quirk.  Thanks to Jim Davis @ HPLabs for
  1006.  **  suggesting this more intuitive behaviour.
  1007.  **
  1008.  **  The old way, for those people that might want to see what the previous
  1009.  **  behaviour was to call next_message with TRUE, not FALSE.
  1010. **************************************************************************/
  1011.                }
  1012.                break;
  1013.  
  1014.         case ctrl('U') : if (message_count < 1) {
  1015.                    error1(catgets(elm_msg_cat, ElmSet, ElmNoItemToUndelete,
  1016.                  "No %s to undelete!"), items);
  1017.                    fflush(stdin);
  1018.                  }
  1019.                  else 
  1020.                    meta_match(UNDELETE);
  1021.                  break;
  1022.  
  1023.         case ctrl('L') : redraw++;    break;
  1024.  
  1025.         case NO_OP_COMMAND : break;    /* noop for timeout loop */
  1026.  
  1027.         case ESCAPE : if (cursor_control) {
  1028.                 key_offset = 1;
  1029.                 ch = ReadCh(); 
  1030.   
  1031.                             if ( ch == '[' || ch == 'O')
  1032.                             {
  1033.                               ch = ReadCh();
  1034.                               key_offset++;
  1035.                             }
  1036.   
  1037.                 if(ch == up[key_offset]) goto prev_undel_msg;
  1038.                 else if(ch == down[key_offset]) goto next_undel_msg;
  1039.                 else if(ch == right[key_offset]) goto next_page;
  1040.                 else if(ch == left[key_offset]) goto prev_page;
  1041.                 else if (hp_terminal) {
  1042.                   switch (ch) {
  1043.                   case 'U':        goto next_page;
  1044.                   case 'V':        goto prev_page;
  1045.                   case 'h':     
  1046.                   case 'H':        goto first_msg;
  1047.                   case 'F':        goto last_msg;
  1048.                   case 'A':
  1049.                   case 'D':
  1050.                   case 'i':        goto next_undel_msg;
  1051.                   case 'B':
  1052.                   case 'I':
  1053.                   case 'C':        goto prev_undel_msg;
  1054.                   default: PutLine2(LINES-3, strlen(Prompt), 
  1055.                     "%c%c", ESCAPE, ch);
  1056.                   }
  1057.                 } else /* false hit - output */
  1058.                   PutLine2(LINES-3, strlen(Prompt), 
  1059.                       "%c%c", ESCAPE, ch);
  1060.               }
  1061.  
  1062.               /* else fall into the default error message! */
  1063.  
  1064.         default    : if (ch > '0' && ch <= '9') {
  1065.                 PutLine1(LINES-3, strlen(Prompt), 
  1066.                     catgets(elm_msg_cat, ElmSet, ElmNewCurrentItem,
  1067.                     "New Current %s"), Item);
  1068.                 i = read_number(ch, item);
  1069.  
  1070.                 if( i > message_count)
  1071.                   error1(catgets(elm_msg_cat, ElmSet, ElmNotThatMany,
  1072.                 "Not that many %s."), items);
  1073.                 else if(selected
  1074.                 && isoff(ifmain(headers[i-1]->status,
  1075.                                     aliases[i-1]->status), VISIBLE))
  1076.                   error1(catgets(elm_msg_cat, ElmSet, ElmNotInLimitedDisplay,
  1077.                 "%s not in limited display."), Item);
  1078.                 else {
  1079.                   current = i;
  1080.                   nucurr = get_page(current);
  1081.                 }
  1082.               }
  1083.               else {
  1084.                  error(catgets(elm_msg_cat, ElmSet, ElmUnknownCommand,
  1085.                   "Unknown command. Use '?' for help."));
  1086.                 fflush(stdin);
  1087.               }
  1088.     }
  1089. }
  1090.